package com.example.demo.stream.parallel;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * @author MarioZzz
 * @create 2023-10-30 10:08
 */
//測量的是目標方法的平均時間
@BenchmarkMode(Mode.AverageTime)
//毫秒計時
@OutputTimeUnit(TimeUnit.MILLISECONDS)
//使用4Gb的堆，測試兩次獲得更準確的結果
@Fork(value = 2, jvmArgs = {"-Xms4G", "-Xmx4G"})
@State(Scope.Thread)
public class AddAll {

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(AddAll.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }

    /**
     * 1 到 1千萬的纍加求和
     */
    private static final long N = 10_000_000L;


    //被測試的目標方法
//    @Benchmark
    public long sequentialSum() {
        return Stream.iterate(1L, i -> i + 1)
                .limit(N)
                .reduce(0L, Long::sum);
    }

    //    @Benchmark
    public long iterativeSum() {
        long res = 0;
        for (long i = 1L; i <= N; i++) {
            res += i;
        }
        return res;
    }

    /**
     * 迭代器的写法比较慢
     * @return
     */
    @Benchmark
    public long parallelSum() {
//        return Stream.iterate(1L, i -> i + 1)
//                .limit(n)
//                .reduce(0L, Long::sum);
        return LongStream.rangeClosed(1, N)
                .parallel().reduce(0L, Long::sum);
    }

    //盡量在每次測試後進行一次gc回收
    @TearDown(Level.Invocation)
    public void tearDown(){
        System.gc();
    }
}
